// 判断是否是监听函数
function isListener(target: any): target is Listener {
  if (Object.prototype.toString.call(target) === "[object Function]") {
    return true;
  } else {
    return false;
  }
}

// 暴露接口
class EventManager implements EventManagerInterface {
  private _events: InnerEvents = {};
  static version = "0.0.3";
  // 绑定事件方法
  on(eventName: string, listener: Listener) {
    // 检测输入参数是否合理
    if (!eventName || !listener) {
      console.error("请检查传入监听的参数是否出现了少传后漏传情况。");
      return this;
    }
    if (!isListener(listener)) {
      console.error("请确保传入的参数格式为回调函数。");
    }
    const listenerList = this._events[eventName] || [];
    this._events[eventName] = listenerList;// 传递引用
    // const listenerIsPlain: boolean = !(typeof listener === "object");
    // 防止重复添加事件
    if (listenerList.indexOf(listener) === -1) {
      listenerList.push(listener);
    }
    return this; // 形成链式调用
  }
  // 单次绑定事件方法
  once(eventName: string, listener: Listener) {
    // 为监听函数添加标记
    listener.__tag__ = "once";
    return this.on(eventName, listener) as this;
  }
  // 解绑某一特殊事件方法
  remove(eventName: string, listener: Listener) {
    const listenerList = this._events[eventName];
    if (!listenerList) {
      return this;
    }
    let removeIndex: number = listenerList.indexOf(listener); // 取得索引
    if (removeIndex > -1) {
      // 如果存在才从函数列表中删除
      listenerList.splice(removeIndex, 1);
    }
    return this;
  }
  // 触发事件方法
  trigger(eventName: string, ...args: any[]) {
    const listenerList = this._events[eventName];
    if (!listenerList || listenerList.length === 0) {
      console.warn(
        "触发失败：此事件不存在需要被触发执行的监听函数，请检查输入的事件名是否有误。"
      );
      return this;
    }
    listenerList.forEach((listener) => {
      listener.apply(this, args); // 调用函数
      if (listener.__tag__ === "once") {// 检测该函数是否具有once标签
        delete listener.__tag__; // 记得删除属性否则会带函数属性引用
        this.remove(eventName, listener);
      }
    });
    return this;
  }
  // 清除某一事件下的所有方法
  delete(eventName: string) {
    let listenerList = this._events[eventName];
    if (listenerList && listenerList.length > 0) {
      this._events[eventName] = [];
    } else {
      console.warn('清除失败：此事件不存在需要被触发执行的监听函数，请检查输入的事件名是否有误。');
    }
    return this;
  }
  // 清除所有事件存储方法
  clear() {
    this._events = {};
    return this;
  }
  // 输出当前事务管理器状态
  status() {
    let message = "";
    Object.keys(this._events).forEach(key => {
      message += ("事件：" + key + "下托管有" + this._events[key].length + " 个方法\n");
    });
    console.log(message === "" ? "目前没有被托管的方法。" : message);
    return this;
  }
}

export default EventManager;
